package com.mooc.encrypt;

import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.utility.JavaModule;
import org.springframework.beans.factory.InitializingBean;

import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

import static net.bytebuddy.matcher.ElementMatchers.named;

@Slf4j
public class EncryptLauncher implements InitializingBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        Instrumentation instrumentation = ByteBuddyAgent.install();

        new AgentBuilder.Default()
                .type(buildEnhanceClassMatch())
                .transform(new Transformer())
                .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
                .installOn(instrumentation);
    }

    private ElementMatcher buildEnhanceClassMatch() {
        Mysql5Instrumentation mysql5Instrumentation = new Mysql5Instrumentation();
        String enhanceClass = mysql5Instrumentation.getEnhanceClass();
        ElementMatcher.Junction judge = named(enhanceClass);
        return judge;
    }

    private class Transformer implements AgentBuilder.Transformer {

        @Override
        public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
                                                final TypeDescription typeDescription,
                                                final ClassLoader classLoader,
                                                final JavaModule module,
                                                final ProtectionDomain protectionDomain) {
            Mysql5Instrumentation mysql5Instrumentation = new Mysql5Instrumentation();
            Mysql5Interceptor mysql5Interceptor = new Mysql5Interceptor();
            // 设置拦截器
            builder = builder.method(named(mysql5Instrumentation.getEnhanceMethod()))
                    .intercept(MethodDelegation.to(mysql5Interceptor));
            return builder;
        }
    }
}
